iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0

集合類型

集合是大多數編程語言的常見概念,通常包含相同類型的一些對象(也可以沒有半個對象)。集合中的對象稱為元素或條目。

  • 以下是Kotlin 相關的集合類型:
    • List : 是一個有序集合,可通過索引(反映元素位置的整數)訪問元素。元素可以在list 中出現多次。列表的一個示例是一句話:有一組字、這些字的順序很重要並且字可以重複。
    • Set : 是唯一元素的集合。它反映了集合(set)的數學抽象:一組無重複的對象。一般來說set 中元素的順序並不重要。例如,字母表是字母的集合(set)。
    • Map : 是一組鍵值對。鍵是唯一的,每個鍵都映射到一個值。值可以重複。map 對於存儲對象之間的邏輯連接非常有用,例如,員工的ID 與員工的位置。
  • list、set、map都提供了唯讀和可變兩種不同的集合:
    • listOf()、setOf()、mapOf() : 唯讀,提供索引供訪問元素。
    • mutableListOf()、mutableSetOf()、mutableMapOf() : 可通過mutator函數來添加、刪除和更新其元素。

宣告一個集合:

// list、set、map宣告方式都一樣:
val numbers =listOf<String>("one","two","three")
val fruits = mutableListOf<String>("apple","banana","pineapple")
  • kotlin的集合也可以類型推斷,尖括號中的類型可省略。
  • 須注意 : 宣告 mutable集合,不需要使用var關鍵字,使用val關鍵字就可以,依然可以對mutable集合的內容做變動,因變數對集合的referance(參考或引用)不變,那這集合做什麼變動是不影響這個reference的,這也是為什麼val宣告的變數應該叫唯讀比較不會令人誤會,不可變是指引用不可變。
  • 索引值的起始為0,以上面例子來說numbers的元素有3個,索引值左至右為0,1,2 numbers[0]為"one",numbers[2]為"three"

list 查找

按索引取元素:

  • get(),或簡化的[]運算子、getValue()
  • getOrElse() : 返回結果或索引不存在就返回預設值。 如:numbers.getOrElse(5, {it})
  • getOrNull() : 預設值為null。 如:numbers.getOrNull(5)

線性查找

  • indexOf(index) : 由左至右查找,以 fruits為例,fruits.indexOf(0) //apple
  • lastIndexOf(index) : 由右至左查找,索引值也會反過來倒著數。如 :fruits.lastIndexOf(2) //apple

符合描述的查找

  • indexOfFirst() : 返回與描述符合的第一個元素的索引值
  • indexOfLast() : 返回與描述符合的最後一個元素的索引值
 val numbers = listOf<Int>(1, 2, 3, 4, 5, 6, 7, 8)
    println(numbers.indexOfFirst { it % 3 == 0 })  //取被3整除的第一個元素(3)的索引: 2 
    println(numbers.indexOfLast { it % 2 == 1 })  // 取奇數的最後一個元素(7)的索引: 6 

mutable list 集合常見的mutator函數:

函數 描述 範例
add 增加元素 numbers.add(1, "two")
addAll 增加另一個集合的所有元素 numbers.addAll(2, listOf("three", "four"))
[ ] set(),在指定位置替换元素,不会更改其他元素的索引 numbers[0] = "zero"
removeAt 刪除某元素 numbers.removeAt(1)、numbers.removeFirst()、numbers.removeLast()
removeAll 刪除和另一個集合相同的所有元素 numbers.removeAll(listOf("three", "four")) 傳入自己的話就跟clear()一樣
clear 刪除所有元素 numbers.clear() //[ ]

mutable list 集合排序用函數

偷懶貼官網範例程式碼

  • sort():升序排序,數字的話由小到大,字串的話依首字母A~Z的先後排序
  • sortDescending() : 反向排序
  • sortBy { } :依據{}中的條件排序
  • sortByDescending {}:依據{}中的條件反向排列
  • shuffle隨機打亂
  • 反過來排,是shuffle的結果的反向
val numbers = mutableListOf("one", "two", "three", "four")

numbers.sort() 
println("Sort into ascending: $numbers")  //Sort into ascending: [four, one, three, two]

numbers.sortDescending()
println("Sort into descending: $numbers") //Sort into descending: [two, three, one, four]

numbers.sortBy { it.length }
println("Sort into ascending by length: $numbers")       // Sort into ascending by length: [two, one, four, three]

numbers.sortByDescending { it.last() }
println("Sort into descending by the last letter: $numbers")    // Sort into descending by the last letter: [four, two, one, three]

numbers.shuffle()
println("Shuffle: $numbers")  //Shuffle: [three, two, four, one]

numbers.reverse()
println("Reverse: $numbers")  //Reverse: [one, four, two, three]

list 和 set 比較:

  • list:有序、資料可以重複
  • Set 跟 list相同之處:使用一樣的尋訪函數、有可變不可變
  • Set 跟 list 區別: set的元素具有唯一性,且不支援基於索引值的存取,因為裡面元素順序不固定(仍然可以讀取特定位置的值)
val planets = setOf("Mercury","Venus","Earth")  // [Mercury, Venus,  Earth]

val planets2 = setOf("Mercury", "Venus", "Earth", "Earth")  // [Mercury, Venus,  Earth]

set集合中的元素具有唯一性,會將重複的元素移除。

和list相似,可以用 contains 跟 containsAll 函數,來檢查是否包含某個或某些元素:

planets.contains("Eath")  //true
planets.contains("Pluto") //false

set不會對元素做索引排序,故不提供[]的內建運算子,但依然可以靠elementAt函數讀取集合某個位置的函數

//讀取第三個元素:
planets.elementAt(2)  //Eath

但是雖然可行,讀取速度卻慢上list一個等級,因為element會依次迭代尋找一個元素,若集合中元素眾多,會比list慢上許多,
所以若有需要依照索引讀取資料的話使用list集合會更適合。

另外set集合雖有可變及不可變之分,但是沒有需要按索引操作的mutator函數(如:list中add(index,element)函數)

若遇到需要一個 不能重複但需要索引值的需求 -> 建立一個set集合去除重複元素然後再轉成list集合使用。
定義空set集合時,無法依賴類型推斷,需要指名類型

var setCollection = setOf<String>()

//然後可以透過 setCollection += element 將元素加入該set集合中

mutable set 集合常見的mutator函數:

函數 描述 範例
add 增加元素 mutableSetOf(1,2).add(3) //[1,2,3]
addAll 增加另一個集合的所有元素 mutableSetOf(1,2).addAll(listOf(1,5,6)) //[1,2,,5,6]
+= 增加1個或多個元素 mutableSetOf(1,2)+=3 //[1,2,3]
-= 刪除1個或多個元素 mutableSetOf(1,2,3) -= listOf(2,3) //[1]
remove 刪除某元素 mutableSetOf(1,2,3).remove(1) //[2,3]
removeAll 刪除和另一個集合相同的所有元素 mutableSetOf(1,2,).removeAll(listOf(1,5,6) //[2])
clear 刪除所有元素 mutableSetOf(1,2).clear() //[ ]

集合轉換:

1.list集合透過toSet()去除重複元素,再用toList()轉回list集合,這樣便可以得到一串沒有重複又可以使用索引的集合。

val planets = setOf("Mercury","Mercury","Venus","Earth").toSet().toList()
planets[0]  //Mercury

2.因為這個方法太常使用,所以kotlin提供了一個快捷函數distinct

val planets = listOf("Mercury","Mercury","Venus","Earth").distinct()
planets[0]  //Mercury

Map

  • map與list 和 set 有不少共通點 : 存放一組元素,預設唯讀,使用參數化類型告訴編譯器集合元素的類型,支援迭代。

  • 不同 : map 取得值是以鍵值(key),不是以索引值,key具有唯一性,對應到具體的值(value),value可以與其他鍵值對的值重複。

val map1 = mapOf('a' to 1, 'b' to 2, ...)
val map2 = mutableMapOf(Pair('a',1), Pair('b',2), Pair('c',3))
         map += Pair('d',5)
         print(map2)
        // {a=1, b=2, c=3, d=5}

使用 key to value的方式較為簡潔,要更動map的內容的話要使用mutableMapOf 才可以。

val map3 = mapOf('a' to 1, 'b' to 2,'a' to 3)
print(map3) //{a=4, b =2}
  • 鍵值具有唯一性,若是強迫重複使用,則舊的value會被新的替換掉。

取值:

val map3 = mapOf('a' to 1, 'b' to 2,'a' to 3)
print(map3['a'])  // 1

map的存取函數

map的存取函數 描述 範例
[ ] get()的簡化寫法;讀取key對應的值,如果不存在就返回null map3['f'] // null
getValue 讀取key對應的值,如果不存在就拋出異常 map3.getValue('f') //NoSuchElementException
getOrElse 讀取key對應的值,或使用匿名函數返回預設值 map3.getOrElse('f'){"No such Element"} // No such Element
getOrDefault 讀取key對應的值,或返回預設值 map3.getOrDefault('f',0.0) // 0.0

mutable map的mutator函數

map的mutator函數 描述 範例
= 增加或更新現有鍵值對
+= plusAssign操作符,增加或更新現有鍵值對 sampleMap += mapOf('x'to 4, 'n' to 5) 、 sampleMap.plusAssign(mapOf(Pair('c',5)))
put 增加或更新現有鍵值對 sampleMap.put("three", 3)
putAll 增加所有傳入的鍵值對 sampleMap.putAll(listOf('c' to 3, 'd' to 4))
getOrPut 鍵值不存在就增加並返回結果;否則則返回現已有的鍵對應的值 'g'鍵不存在故增加: sampleMap.getOrPut('g'){7} //7 'g'鍵存在返回現有值:sampleMap.getOrPut('g'){5} //7
remove 從Map集合中刪除指定鍵值對 sampleMap.remove('a')
- 刪除指定鍵值對,返回新的Map集合 val sampleMap =mutableMapOf('a' to 1, 'b' to 2) - 'a' //{'b'=2}
-= 刪除指定鍵值對 sampleMap -= 'a'
clear 清除Map集合 sampleMap.clear() //{}

小結 : List、Set 和 Map 的比較

集合類型 是否有序 是否唯一 儲存
List Y N 元素
Set N Y 元素
Map N Y 鍵值對

參考: kotlin權威2.0、文檔


上一篇
第19天 Kotlin小學堂(8) : 函數類型、Lambda
下一篇
第21天 Kotlin小學堂(10) : Class 類別
系列文
新手向Android&Kotlin學習紀錄30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言